package com.imooc.security;

import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Objects;

import javax.crypto.Cipher;
import javax.crypto.KeyAgreement;
import javax.crypto.SecretKey;
import javax.crypto.interfaces.DHPublicKey;
import javax.crypto.spec.DHParameterSpec;

import org.apache.commons.codec.binary.Base64;
import org.junit.Test;

/**
 * 非对称加密：DH,Diffie-Hellman,密钥交换
 * @author Administrator
 *
 */
public class ImoocDH {
	private static String srcStr = "imooc security dh";
	
	@Test
	public void jdkDh(){
		try {
			//1.初始化发送方的密钥
			KeyPairGenerator senderKeyPairGenerator = KeyPairGenerator.getInstance("DH");
			senderKeyPairGenerator.initialize(512);
			KeyPair senderKeyPair = senderKeyPairGenerator.generateKeyPair();
			byte[] senderPublicKeyEnc = senderKeyPair.getPublic().getEncoded();//发送方公钥，发送给接收方
			
			//2.初始化接收方密钥
			KeyFactory recevierKeyFactory = KeyFactory.getInstance("DH");
			X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(senderPublicKeyEnc);
			PublicKey recevierPublicKey = recevierKeyFactory.generatePublic(x509EncodedKeySpec);
			DHParameterSpec dhParameterSpec = ((DHPublicKey)recevierPublicKey).getParams();
			KeyPairGenerator recevicerKeyPairGenerator = KeyPairGenerator.getInstance("DH");
			recevicerKeyPairGenerator.initialize(dhParameterSpec);
			KeyPair recevierKeypair = recevicerKeyPairGenerator.generateKeyPair();
			PrivateKey recevierPrivateKey = recevierKeypair.getPrivate();
			byte[] receiverPublicKeyEnc = recevierKeypair.getPublic().getEncoded();
			
			//3.密钥构建
			KeyAgreement recevierKeyAgreement = KeyAgreement.getInstance("DH");
			recevierKeyAgreement.init(recevierPrivateKey);
			recevierKeyAgreement.doPhase(recevierPublicKey, true);
			SecretKey recevierDesKey = recevierKeyAgreement.generateSecret("DES");
			
			KeyFactory senderKeyFactory = KeyFactory.getInstance("DH");
			x509EncodedKeySpec = new X509EncodedKeySpec(receiverPublicKeyEnc);
			PublicKey senderPublicKey = senderKeyFactory.generatePublic(x509EncodedKeySpec);
			KeyAgreement senderKeyAgreement = KeyAgreement.getInstance("DH");
			senderKeyAgreement.init(senderKeyPair.getPrivate());
			senderKeyAgreement.doPhase(senderPublicKey, true);
			SecretKey senderDesKey = senderKeyAgreement.generateSecret("DES");
			if(Objects.equals(recevierDesKey, senderDesKey)){
				System.out.println("双方密钥相同");
			}
			
			//4.加密
			Cipher cipher  = Cipher.getInstance("DES");
			cipher.init(Cipher.ENCRYPT_MODE, senderDesKey);
			byte[] result = cipher.doFinal(srcStr.getBytes());
			String resultStr = Base64.encodeBase64String(result);
			System.out.println("JDK DH ENCRYPT 加密:"+resultStr);
			
			//5.解密
			cipher.init(Cipher.DECRYPT_MODE, recevierDesKey);
			result = cipher.doFinal(result);
			resultStr = new String(result);
			System.out.println("JDK DH DECRYPT 解密："+resultStr);
			
		} catch (Exception e) {
			e.printStackTrace();
		}
		
	}
}
